﻿using llm_net.Infrastructure.Helpers;
using llm_net.Models;
using llm_net.Services.Abstractions;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace llm_net.Services.Implementations
{
    /// <summary>
    /// 推荐服务
    /// </summary>
    public class RecommendationService : IRecommendationService
    {
        private readonly IVectorDbService _vectorDbService;
        private readonly ITongyiApiService _tongyiApiService;
        private readonly ILogger<RecommendationService> _logger;

        public RecommendationService(IVectorDbService vectorDbService, ITongyiApiService tongyiApiService, ILogger<RecommendationService> logger)
        {
            _vectorDbService = vectorDbService;
            _tongyiApiService = tongyiApiService;
            _logger = logger;
        }
        public async Task<List<Product>> GetRecommendationsAsync(List<TagWithWeightDto> userPreferences, int topK = 5)
        {
            // 1. 基于向量的推荐
            var vectorBasedProducts = await GetVectorBasedRecommendations(userPreferences, topK);

            //// 2. 基于规则的推荐（直接匹配标签）
            //var ruleBasedProducts = await GetRuleBasedRecommendations(userPreferences, topK);

            // 3. 混合结果
            return CombineRecommendations(vectorBasedProducts, topK);
        }
        /// <summary>
        /// 基于向量相似度的推荐实现
        /// </summary>
        private async Task<List<Product>> GetVectorBasedRecommendations(List<TagWithWeightDto> userPreferences, int topK)
        {
            // 设置一个相似度阈值，比如 0.5
            const float similarityThreshold = 0.5f;
            if (userPreferences == null || !userPreferences.Any())
            {
                return new List<Product>();
            }
            try
            {
                // 生成用户偏好向量
                var userVector = await GenerateUserPreferenceVectorAsync(userPreferences);

                // 从向量数据库获取相似商品（获取更多候选以提高多样性）
                var candidates = await _vectorDbService.SearchSimilarProductsAsync(userVector, topK * 2);

                // 添加相似度分数（如果向量数据库未直接返回）
                var productsWithScores = candidates.Select(p => new
                {
                    Product = p,
                    Score = VectorMathHelper.CosineSimilarity(p.Vector, userVector)
                })
                .Where(x => x.Score >= similarityThreshold) // 只保留相似度高的
                .OrderByDescending(x => x.Score)
                .ToList();

                // 记录推荐结果用于调试
                _logger.LogInformation($"向量推荐结果: {string.Join(", ", productsWithScores.Select(p => $"{p.Product.Name}({p.Score:F4})"))}");

                return productsWithScores.Take(topK).Select(x => x.Product).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "向量推荐失败，回退到空结果");
                return new List<Product>();
            }
        }
        /// <summary>
        /// 混合两种推荐结果
        /// </summary>
        private List<Product> CombineRecommendations(
            List<Product> vectorBasedProducts,
            int topK)
        {
            // 使用 HashSet 去重
            var uniqueProducts = new HashSet<string>(); // 存储商品 ID
            var combinedResults = new List<Product>();

            // 1. 优先添加向量推荐结果（通常更具多样性）
            foreach (var product in vectorBasedProducts)
            {
                if (uniqueProducts.Add(product.Id) && combinedResults.Count < topK)
                {
                    combinedResults.Add(product);
                }
            }
            _logger.LogInformation($"混合推荐结果: {string.Join(", ", combinedResults.Select(p => p.Name))}");

            return combinedResults;
        }

        /// <summary>
        /// 生成用户偏好向量
        /// </summary>
        /// <param name="userPreferences"></param>
        /// <returns></returns>
        private async Task<float[]> GenerateUserPreferenceVectorAsync(List<TagWithWeightDto> userPreferences)
        {

            var tasks = userPreferences.Select(async preference =>
            {
                // 添加 "商品类别:" 前缀（需根据实际业务调整）
                var enhancedTag = $"{preference.Label}";
                var vector = await _tongyiApiService.GetTextEmbeddingAsync(enhancedTag);
                return new { Vector = vector, Weight = preference.Weight };
            }).ToList();

            var tagVectors = await Task.WhenAll(tasks);

            if (!tagVectors.Any())
            {
                return Array.Empty<float>();
            }

            var combinedVector = new float[tagVectors[0].Vector.Length];
            float totalWeight = 0;

            foreach (var tagVector in tagVectors)
            {
                for (int i = 0; i < tagVector.Vector.Length; i++)
                {
                    combinedVector[i] += tagVector.Vector[i] * tagVector.Weight;
                }
                totalWeight += tagVector.Weight;
            }

            if (totalWeight > 0)
            {
                for (int i = 0; i < combinedVector.Length; i++)
                {
                    combinedVector[i] /= totalWeight;
                }
            }

            return combinedVector;
        }
    }
}
